#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "evalsoc.h"


#include "test_uart.h"
#include "evalsoc_uart.h"
#include "test_dma.h"


// 寄存器直接访问宏
#define REG_READ(add)   (*(volatile uint32_t *)(add))
#define UART_TXCTRL_ADDR (UART0 + UART_REG_TXCTRL)

/**
 * brief  DMA 传输 内存到 UART 外设
 * @param  puart: UART 外设号
 * @param  uart_base: UART 外设寄存器地址
 * @param  channer: DMA 通道号
 * @param  dma_tx_req: DMA 发送请求
 * @param  Memory_addr: 内存地址
 * @param  len: 传输长度
 * @retval 0: 成功
 */
int dbg_test_dma_uart_tx(dw_uart_regs_t * puart,uint32_t uart_base,uint32_t channer,uint32_t dma_tx_req,uint32_t Memory_addr,uint32_t len){

	struct dw_dma_regs *dma_regs = (struct dw_dma_regs *)0x00100000;
	uint8_t temp[len];	
		
	
	memset((void *)Memory_addr,0xAA,len);

	dma_init_M2P(channer,dma_tx_req,Memory_addr,uart_base,0,0,len); //内存到UART外设

	for(int i=0;i<len;i++){
		temp[i] = uart_read(puart);
		if (temp[i]!= 0xAA)
		{
			printf("tx error\r\n");
			return -1;
		}
	}
	// 等待DMA传输完成
    while (dma_regs->CH_EN & (0x1<<channer)){
		//等待循环结束
	}
    			
	printf("dma uart tx success\r\n");

	return 0;
}
/**
 * brief: DMA 传输 UART外设到内存
 * @param  puart: UART外设号
 * @param  uart_base: UART 外设寄存器地址
 * @param  channer: DMA 通道号
 * @param  dma_rx_req: DMA 接收请求
 * @param  Memory_addr: 内存地址
 * @param  len: 传输长度
 * @retval 0: 成功
 */
int dbg_test_dma_uart_rx(dw_uart_regs_t * puart,uint32_t uart_base,uint32_t channer,uint32_t dma_rx_req,uint32_t Memory_addr,uint32_t len){

	struct dw_dma_regs *dma_regs = (struct dw_dma_regs *)0x00100000;

    dma_init_P2M(channer,dma_rx_req,uart_base,Memory_addr,0,0,len); //UART外设到内存

    for(uint16_t i=0;i<len;i++){
		uart_write(puart,0xAA);
	}   

	//uart_write(puart,0x00);

	while (dma_regs->CH_EN & (0x1<<channer)); // 等待DMA传输完成

    for(uint16_t i=0;i<len;i++){
        if((read_reg(Memory_addr) & 0xFF) != 0xAA){
            Memory_addr += 1;
            printf("rx error\r\n");
            return -1;
        }
    }
	printf("dma uart rx success\r\n");
	return 0;
}

/**
 * brief: UART 回环测试
 * @param  puart: UART 外设号
 * @return 0
 */
int uart_Loopback_test(dw_uart_regs_t *puart){
	uint8_t temp;

	uart_init(puart,9600,Loopback_Mode_Enable,RCVR_Trigger_CHAR_1,DATA_BITS_8,PARITY_NONE,STOP_BITS_1);

	for (uint16_t i = 0; i < 200; i++){
		uart_write(puart,0xaa);
		temp = uart_read(puart);
		if(temp != 0xaa){
			printf("uart loopback error: %d\r\n",temp);	
			break;
		}
	 }
	
	//正常模式
	uart_init(puart,9600,Loopback_Mode_Disable,RCVR_Trigger_CHAR_1,DATA_BITS_8,PARITY_NONE,STOP_BITS_1);

	return 0;
}

// 数据位测试
void test_data_bits(dw_uart_regs_t *puart)
{
    const data_bits_t bits[] = {DATA_BITS_5, DATA_BITS_6, DATA_BITS_7, DATA_BITS_8};
	uint8_t testdata[] = {0xF8, 0xFC, 0xFE, 0xFF};
    
    for (int i = 0; i < 4; i++) {
        uart_init(puart, 9600, Loopback_Mode_Disable, RCVR_Trigger_CHAR_1,
                 bits[i], STOP_BITS_1, PARITY_NONE);

        // 根据数据位计算掩码
        uint8_t mask = (1 << bits[i]) - 1;
        uint8_t test_data = testdata[i] & mask; //18 3c 7e ff
        uart_write(puart, test_data);
		//延时
		for(int m=0;m<100000;m++){
			__NOP();
		}
     
    }
}


// 奇偶校验测试
void test_parity(dw_uart_regs_t *puart)
{
    const parity_t parity[] = {PARITY_NONE, PARITY_ODD, PARITY_EVEN};
    
    for (int i = 0; i < 3; i++) {
        uart_init(puart, 9600, Loopback_Mode_Disable, RCVR_Trigger_CHAR_1,
                 DATA_BITS_8, STOP_BITS_1, parity[i]);

        // 测试奇数/偶数校验位
        uint8_t test_data[] = {0x00, 0x7F, 0x55, 0xAA};
        for (int m = 0; m < 4; m++) {
            uart_write(puart, test_data[m]);
        }
		//延时
		for(int m=0;m<100000;m++){
			__NOP();
		}
    }
}


// 停止位配置验证
void test_stop_bits_config(dw_uart_regs_t *puart)
{
    const stop_bits_t stops[] = {STOP_BITS_1, STOP_BITS_1_5, STOP_BITS_2};
	uint8_t test_data[] = {0x11, 0x22, 0x33, 0x44};

    for (int i = 0; i < 3; i++) {
		if(i ==0 || i ==2){
			uart_init(puart, 9600, Loopback_Mode_Disable, RCVR_Trigger_CHAR_1,DATA_BITS_8, stops[i], PARITY_NONE);
			for(int m=0;m<4;m++){
				uart_write(puart,test_data[m]);
			}
			//延时
			for(int m=0;m<100000;m++){
				__NOP();
			}
		}else{//1.5停止位，需在数据位为5时才能配置
			uart_init(puart, 9600, Loopback_Mode_Disable, RCVR_Trigger_CHAR_1,DATA_BITS_5, stops[i], PARITY_NONE);
			for(int m=0;m<4;m++){
				uart_write(puart,test_data[m]);
			}
			//延时
			for(int m=0;m<100000;m++){
				__NOP();
			}
		}		
    }
}



/**
 * @brief: DMA UART0 RX/TX 测试用例
 * 
 */
void dma_uart0_case( void ){
	uart_init(UART0,9600,Loopback_Mode_Enable,RCVR_Trigger_CHAR_1,DATA_BITS_8,PARITY_NONE,STOP_BITS_1);
	dbg_test_dma_uart_tx(UART0,UART0_BASE,0,10,0x00090000,501); //UART0 DMA TX
	dbg_test_dma_uart_rx(UART0,UART0_BASE,1,11,0x00090300,201); //UART0 DMA RX
	uart_init(UART0,9600,Loopback_Mode_Disable,RCVR_Trigger_CHAR_1,DATA_BITS_8,PARITY_NONE,STOP_BITS_1);
}

/**
 * @brief: DMA UART1 RX/TX 测试用例
 */
void dma_uart1_case( void ){
	uart_init(UART1,9600,Loopback_Mode_Enable,RCVR_Trigger_CHAR_1,DATA_BITS_8,PARITY_NONE,STOP_BITS_1);
	dbg_test_dma_uart_tx(UART1,UART1_BASE,2,12,0x00090500,501); //UART1 DMA TX
	dbg_test_dma_uart_rx(UART1,UART1_BASE,3,13,0x00090800,201); //UART1 DMA RX
	uart_init(UART1,9600,Loopback_Mode_Disable,RCVR_Trigger_CHAR_1,DATA_BITS_8,PARITY_NONE,STOP_BITS_1);
}